#include <iostream>
#include <chrono>
#include <thread>
#include <algorithm>
//#include <curses.h>
//#include <csignal>
#include "utils.h"
#include "cap_mgr.h"
#include "proc.h"
#include "name_res.h"
#include "settings.h"
#include "epoll_stdin.h"

namespace {
    volatile bool quit = false;

    class curses_setup {
        static char BPS[],
                KBPS[],
                MBPS[],
                GBPS[];

        static void recv_send_format(const std::chrono::nanoseconds &tm_elapsed, const size_t recv, const size_t sent,
                                     double &recv_d, double &sent_d, const char *&fmt) {
            const double tm_fct = 1000000000.0 / tm_elapsed.count();
            const size_t max_bytes = tm_fct * ((recv > sent) ? recv : sent);
            if (max_bytes >= 1024 * 1024 * 1024) {
                const double cnv_fct = 1.0 / (1024.0 * 1024.0 * 1024.0);
                recv_d = cnv_fct * recv * tm_fct;
                sent_d = cnv_fct * sent * tm_fct;
                fmt = GBPS;
            } else if (max_bytes >= 1024 * 1024) {
                const double cnv_fct = 1.0 / (1024.0 * 1024.0);
                recv_d = cnv_fct * recv * tm_fct;
                sent_d = cnv_fct * sent * tm_fct;
                fmt = MBPS;
            } else if (max_bytes >= 1024) {
                const double cnv_fct = 1.0 / 1024.0;
                recv_d = cnv_fct * recv * tm_fct;
                sent_d = cnv_fct * sent * tm_fct;
                fmt = KBPS;
            } else {
                recv_d = tm_fct * recv;
                sent_d = tm_fct * sent;
                fmt = BPS;
            }
        }

    public:
        explicit curses_setup() = default;

        static void
        redraw(const std::chrono::nanoseconds &tm_elapsed, nettop::ps_vec &ps_v, const nettop::proc_mgr::stats &st) {
            for (const auto &i : ps_v) {
                std::string r_cmd = i.cmd;
                double r_d = 0.0;
                double s_d = 0.0;
                const char *fmt = "";
                recv_send_format(tm_elapsed, i.total_rs.first, i.total_rs.second, r_d, s_d, fmt);
                printf("%6d  %10.2f %10.2f  %-5s \n", i.pid, r_d, s_d, fmt);
            }
        }
    };

    char    curses_setup::BPS[] = "Byte/s",
            curses_setup::KBPS[] = "KiB/s ",
            curses_setup::MBPS[] = "MiB/s ",
            curses_setup::GBPS[] = "GiB/s ";


}

int main(int argc, char *argv[]) {
    try {
            using namespace std::chrono;

            nettop::packet_list p_list;
            nettop::cap_mgr			c;
            nettop::local_addr_mgr lam;
            nettop::async_log_list log_list;

            // create cap thread
            std::thread			cap_th(&nettop::cap_mgr::async_cap, &c, std::ref(p_list), std::ref(quit));
            cap_th.detach();

            system_clock::time_point latest_time = std::chrono::system_clock::now();
           // while (true){
                nettop::proc_mgr p_mgr;
                nettop::proc_mgr::stats mgr_st;
                nettop::ps_vec p_vec;
                sleep(1);
                const system_clock::time_point cur_time = std::chrono::system_clock::now();
                std::list<nettop::packet_stats> ps_list;
                p_list.swap(ps_list);
                mgr_st.total_pkts = p_list.total_pkts.exchange(0);
                p_mgr.bind_packets(ps_list, lam, p_vec, mgr_st, log_list);
                // redraw 函数 内部有一个打印函数，这里有需要的信息
                curses_setup::redraw(cur_time - latest_time, p_vec, mgr_st);
                latest_time = cur_time;
         //   }



    } catch (const std::exception &e) {
        std::cerr << "Exception: " << e.what() << std::endl;
    } catch (...) {
        std::cerr << "Unknown exception" << std::endl;
    }
}
